/*所用库*/
#include <Arduino.h>
#include <OneButton.h>
#include <FastLED.h>
#include <TFT_eSPI.h>
#include <Ticker.h>
#include <WiFi.h>
#include "PubSubClient.h" ////A client library for MQTT messaging.
#include "DHT.h"
#include <ArduinoJson.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <NTPClient.h>//时间服务提供程序
#include "ftf.h" 

/*基本引脚定义*/
#define LED_PIN 13     // led引脚
#define NUM_LED 12     // LED数量
#define Button_PIN1 21 // 按钮1引脚
#define Button_PIN2 22 // 按钮1引脚
const int irPin = 2;   // 红外接收模块连接的GPIO引脚
/*DHT11温湿度传感器引脚定义*/
#define DHTPIN 32 // Defines pin number to which the sensor is connected
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE); // Creats a DHT object
/* 连接WIFI SSID和密码 */
#define WIFI_SSID "HONOR 50"   // 待更改 热点名称
#define WIFI_PASSWD "1626614702hzw" // 待更改 热点密码
/* 设备的三元组信息*/           // 需更改 云平台信息 以下为我阿里云所用信息
#define PRODUCT_KEY "a1OwMdLRSp4"
#define DEVICE_NAME "ESP_DHT11"
#define DEVICE_SECRET "26c4d1a18106bd4ce8956213c3af94c0"
#define REGION_ID "cn-shanghai"
/* 线上环境域名和端口号，不需要改 */
#define MQTT_SERVER PRODUCT_KEY ".iot-as-mqtt." REGION_ID ".aliyuncs.com"
#define MQTT_PORT 1883
#define MQTT_USRNAME DEVICE_NAME "&" PRODUCT_KEY
/* 线上环境ID与协议密码，需要更改 */
#define CLIENT_ID "a1OwMdLRSp4.ESP_DHT11|securemode=2,signmethod=hmacsha256,timestamp=1716965651474|"
#define MQTT_PASSWD "1044f7da31f32d096f8d1e08810e6eef5258e232903ca1b8d1d3ceee20597327"
/*宏定义订阅主题*/
#define ALINK_BODY_FORMAT "{\"id\":\"ESP_DHT11\",\"version\":\"1.0\",\"method\":\"thing.event.property.post\",\"params\":%s}"
#define ALINK_TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post"
const char *TOPIC = "/sys/a1OwMdLRSp4/ESP_DHT11/thing/service/property/set";
unsigned long lastMs = 0;


float soil_data; // 湿度
float tep;       // 温度
/*lvgl上传温湿度所用参数*/
float Te; // 读取暂存
float Hu; // 读取暂存

CRGB leds[NUM_LED]; // fastLED初始化ws2812b

OneButton button1(Button_PIN1, true); // OneButton初始化
OneButton button2(Button_PIN2, true);

unsigned char flag1 = 0;   // 按钮控制LED参数
unsigned char flagALL = 0; // 总开关 以红外控制为主 按钮也可

//RTOS

void click1();
void click2();
void getTemperature();
void wifiInit();                                                // 连接wifi
void mqttCheckConnect();                                        // 连接mqtt
void mqttIntervalPost();                                        // 上传温湿度
void callback(char *topic, byte *payload, unsigned int length); // 回调函数 云端开灯判断
void LED_Bright();
void LD3320_LED();
void Display_Time();
void Display_Weather();



void task1(void *pvParameters)
{
  /*按钮开灯*/
  while (1)
  {
    int irState = digitalRead(irPin); // 读取红外接收引脚的状态
    if (flagALL == 1)                 // 红外判断
    {
      if (irState == HIGH) // 如果红外接收引脚为高电平（距离内没有照射到东西）
      {
        delay(5000);
        for (int i = 0; i < NUM_LED; i++)
        {
          FastLED.setBrightness(0); // 设置亮度（可选）
          leds[i] = CRGB(0, 0, 0);  // 设置LED颜色
          FastLED.show();           // 更新LED显示
          flag1 = 0;
        }
        flagALL = 0;

      }
      else
      {
        flagALL = 1;
        LED_Bright();
        
      }
    }
    vTaskDelay(5);
  }
}

void task2(void *pvParameters)
{
  /*MQTT协议*/
  while (1)
  {
    TickType_t tStart = xTaskGetTickCount();

    if (millis() - lastMs >= 5000)
    {
      lastMs = millis();
      mqttCheckConnect();
      /* 上报 */
      mqttIntervalPost();
    }
    client.loop();
    // Serial.println("2");
   
    vTaskDelayUntil(&tStart, 2000);
  }
}

void task3(void *pvParameters)
{
  while (1)
  {
    TickType_t tStart = xTaskGetTickCount();

    float h = dht.readHumidity();
  // 读取温度为摄氏温度（默认）
    float t = dht.readTemperature();
  // 将温度读取为华氏度
    float f = dht.readTemperature(true);

    if (isnan(h) || isnan(t) || isnan(f)) {
      Serial.println(F("无法从DHT传感器读取！ "));
      return;
    }
  // 计算华氏热量指数（默认值）
    float hif = dht.computeHeatIndex(f, h);
  // 计算摄氏温度指数
    float hic = dht.computeHeatIndex(t, h, false);

    Serial.print(F("湿度："));
    Serial.print(h);
    Serial.print(F("%  温度: "));
    Serial.print(t);
    Serial.print(F("°C "));

   tft.fillRect(50,100,60,16,TFT_BLACK);   //清屏
    showMyFonts(5, 100, "湿度", TFT_YELLOW);
    tft.setCursor(38, 100, 1);                
    tft.setTextColor(TFT_CYAN);       
    tft.setTextSize(2);                
    tft.println(":"); 
    tft.setCursor(50, 100, 1);                
    tft.setTextColor(TFT_CYAN);       
    tft.setTextSize(2);    
    tft.println(h);     
       
    tft.fillRect(50,120,60,16,TFT_BLACK);   //清屏
    showMyFonts(5, 120, "温度", TFT_YELLOW);
    tft.setCursor(38, 120, 1);                
    tft.setTextColor(TFT_CYAN);       
    tft.setTextSize(2);                
    tft.println(":");      
    tft.setCursor(50, 120, 1);             
    tft.setTextColor(TFT_CYAN);       
    tft.setTextSize(2);    
    tft.println(t);   
    showMyFonts(110, 120, "℃", TFT_YELLOW);     

   delay(50);
   Display_Time();
   delay(50);
   Display_Weather();
   delay(50);

    vTaskDelayUntil(&tStart, 2500);
  }
}



void setup()
{
  Serial.begin(9600);  // TFT
  Serial2.begin(9600); // LD3320A

  tft.init();
  tft.fillScreen(TFT_BLACK);   // 清除屏幕
  tft.setTextSize(2);          // 设置文本大小
  tft.setTextColor(TFT_WHITE); // 设置文本颜色
  tft.setCursor(0, 0);         // 设置文本位置
  tft.setRotation(3);          /* Landscape orientation, flipped */

  button1.reset();             // 清除一下按钮状态机的状态
  button1.attachClick(click1); // 按钮1 开灯
  button2.reset();             // 清除一下按钮状态机的状态
  button2.attachClick(click2); // 按钮2 总开关

  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LED);
  pinMode(irPin, INPUT_PULLUP); // 设置红外接收引脚为输入模式，并启用内部上拉电阻

  dht.begin();
  wifiInit();
  client.setServer(MQTT_SERVER, MQTT_PORT); /* 连接MQTT服务器 */
  client.setCallback(callback);             // 设定回调方式，当ESP32收到订阅消息时会调用此方法

  tft.setRotation(4);    //设置显示镜像 + 旋转90°
  tft.fillRect(0,0,128,60,TFT_BLACK);  //上部分清屏
  tft.drawLine(0,23, 128, 23, TFT_WHITE);  //画线   
  // tft.drawLine(0,60, 128, 60, TFT_WHITE);  //画线
  tft.fillRect(0,61,128,40,TFT_BLACK);  //下一部分清屏
  tft.drawLine(0,93, 128, 93, TFT_WHITE);  //画线 

  timeClient.begin();
  timeClient.setTimeOffset(28800);  // + 1区 偏移3600， +8区 ：3600×8 = 28800
  tft.setSwapBytes(true);              // RGB->BGR，更改显示颜色模式。

  /*freertos定义：         函数名 任务名 堆栈大小 输入参数 优先级 句柄 核心*/
  xTaskCreatePinnedToCore(task1, "LED ", 1028, NULL, 2, NULL, 1);
  xTaskCreatePinnedToCore(task2, "MQTT", 8192, NULL, 2, NULL, 1);
  xTaskCreatePinnedToCore(task3, "TFT ", 8192, NULL, 1, NULL, 1);
}

void loop()
{
  button1.tick(); // onebutton库按钮初始化
  button2.tick();

  LD3320_LED();
  delay(5);

}


void click1()
{
  // Serial.println("click");
  flag1 = flag1 + 1;
  if (flag1 == 4)
  {
    flag1 = 0;
  }
  // Serial.println("button1");
}

void click2()
{
  flagALL = !flagALL;
  // Serial.println("button2");
}

void getTemperature()
{
  Te = dht.readTemperature();
  Hu = dht.readHumidity();
  Serial.println(Te);
  Serial.println(Hu);
}

// 连接wifi
void wifiInit()
{
  WiFi.begin(WIFI_SSID, WIFI_PASSWD);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    Serial.println("WiFi not Connect");
  }
}

// mqtt连接
void mqttCheckConnect()
{
  while (!client.connected())
  {
    Serial.println("Connecting to MQTT Server ...");
    if (client.connect(CLIENT_ID, MQTT_USRNAME, MQTT_PASSWD))
    {
      Serial.println("MQTT Connected!");
    }
    else
    {
      Serial.print("MQTT Connect err:");
      Serial.println(client.state());
      delay(5000);
    }
  }
}

// 上传温湿度
void mqttIntervalPost()
{
  char param[32];
  char jsonBuf[128];

  // upload humidity
  soil_data = dht.readHumidity();
  sprintf(param, "{\"humidity\":%2f}", soil_data);
  sprintf(jsonBuf, ALINK_BODY_FORMAT, param);
  Serial.println(jsonBuf);
  boolean b = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
  if (b)
  {
    Serial.println("publish humidity success");
  }
  else
  {
    Serial.println("publish humidity fail");
  }

  // Upload temperature
  tep = dht.readTemperature();
  sprintf(param, "{\"temperature\":%2f}", tep);
  sprintf(jsonBuf, ALINK_BODY_FORMAT, param);
  Serial.println(jsonBuf);
  boolean c = client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
  if (c)
  {
    Serial.println("publish Temperature success");
  }
  else
  {
    Serial.println("publish Temperature fail");
  }
}

// 回调函数
void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic); // 打印主题信息
  Serial.print("] ");
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]); // 打印主题内容
  }
  Serial.println();

  DynamicJsonDocument doc(1024);                 // 创建了一个名为 doc 的动态 JSON 文档
  deserializeJson(doc, String((char *)payload)); // 从一个名为 payload 的数据中解析 JSON 数据并将其填充到 doc 中

  int a = doc["params"]["led"];

  // DynamicJsonDocument params = doc["params"];

  Serial.println(a);

  if (a == 1)
  {
    flagALL = 1;
    flag1 = 1;
  }
  if (a == 2)
  {
    flagALL = 1;
    flag1 = 2;
  }
  if (a == 3)
  {
    flagALL = 1;
    flag1 = 3;
  }
  if (a == 0)
  {
    flagALL = 0;
    flag1 = 0;
    
    for (int i = 0; i < NUM_LED; i++)
    {
      FastLED.setBrightness(0); // 设置亮度（可选）
      leds[i] = CRGB(0, 0, 0);  // 设置LED颜色
      FastLED.show();           // 更新LED显示
    }
  }
  }


void LED_Bright()
{
  if (flag1 == 2)
  {
    for (int i = 0; i < NUM_LED; i++)
    {
      FastLED.setBrightness(128);    // 设置亮度（可选）
      leds[i] = CRGB(177, 202, 255); // 设置LED颜色
      FastLED.show();                // 更新LED显示
    }
    Serial.println("mode1");
  }
  else if (flag1 == 1)
  {
    for (int i = 0; i < NUM_LED; i++)
    {
      FastLED.setBrightness(128);   // 设置亮度（可选）
      leds[i] = CRGB(255, 157, 63); // 设置LED颜色
      FastLED.show();               // 更新LED显示
    }
    Serial.println("mode2");
  }

  else if (flag1 == 3)
  {
    for (int i = 0; i < NUM_LED; i++)
    {
      FastLED.setBrightness(255);    // 设置亮度（可选）
      leds[i] = CRGB(255, 255, 255); // 设置LED颜色
      FastLED.show();                // 更新LED显示
    }
    Serial.println("mode3");
  }

  else if (flag1 == 0)
  {
    for (int i = 0; i < NUM_LED; i++)
    {

      FastLED.setBrightness(0); // 设置亮度（可选）
      leds[i] = CRGB(0, 0, 0);  // 设置LED颜色
      FastLED.show();           // 更新LED显示
      Serial.println("mode0");
    }
  }
}

void LD3320_LED()
{
  
    char incomingByte = Serial2.read();       //开灯
    if (incomingByte == '3')
    {
      flag1 = 2;
      flagALL = 1;
      Serial.println("open");
    }
    else if (incomingByte == '4')             //关灯
    {
      flagALL = 0;
      flag1 = 0;
      for (int i = 0; i < NUM_LED; i++)
    {

      FastLED.setBrightness(0); // 设置亮度（可选）
      leds[i] = CRGB(0, 0, 0);  // 设置LED颜色
      FastLED.show();           // 更新LED显示
    }
  }
  else if (incomingByte == '2')               //变亮
    {
      flag1 = flag1 + 1 ;
      if(flag1 >= 3)
      {
        flag1 == 3;
      }
  }
  else if (incomingByte == '1')             //变暗
    {
      flag1 = flag1 - 1;
      if(flag1 <= 0)
      {
        flag1 == 0;
      }
  }
}



